package team.com.demo;


import java.awt.Color;
import java.awt.Font;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.Iterator;



/**
 *
 * @author 李惠来（LiHuilai）<a href="http://blog.csdn.net/im1046061426">CSDN博客</a>
 * 邮箱：huilai475@163.com QQ：1046061426
 */
  

  
public class Broadcast extends Thread {
    private ChatUI chatUI;
    private DatagramPacket receive;
    private DatagramPacket sendPack;
    private DatagramSocket client;
    private DatagramSocket server;
    private InetAddress inetAddress;
    private String message;
    private final static String protocolFlag = "f3g4132fdg3213fds1ga31g31sdf32";//协议标记
    private final static String flag = "#";//字符串分隔符
    private String type;
    private String text;
    private String nickname;//存储本地的昵称
    private Font font;
    private Color fontColor;       
    private String hostname;
    private ArrayList<OnlineUser> onlineUsers;
    //private HashSet onlineUsers;
    private OnlineUser onlineUser;
    
    public Broadcast() {
        receive = new DatagramPacket(new byte[1024], 1024);
        try {
            server = new DatagramSocket(8888);
        } catch (SocketException ex) {
            Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            hostname = InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException ex) {
            Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
        }
        type="";
        nickname="null";
        font=new Font("宋体",Font.PLAIN,14);
        fontColor=Color.black;
        text="";
        onlineUsers =new ArrayList();
    }
   
    public ArrayList getOnlineUsers(){
        return this.onlineUsers;
    }
    public void setChatUI(ChatUI chatUI){
        this.chatUI=chatUI;
    }
    public String getNickname(){
        return this.nickname;
    }
    public void setNickname(String nickname){
        this.nickname=nickname;
    }
    public Font getFont(){
        return this.font;
    }
    public void setFont(Font font){
        this.font=font;
    }
    public void setFont(String fontName,int style,int fontSize){
        this.font=new Font(fontName,style,fontSize);
    }
    public Color getFontColor(){
        return this.fontColor;
    }
    public void setFontColor(int red,int green,int blue){
        this.fontColor=new Color(red,green,blue);
    }
    public void setFontColor(Color fontColor){
        this.fontColor=fontColor;
    }
   
    public void send(String text) {

        try {
            byte[] message=text.getBytes("gb2312");
            /*
            * 这里使用了本地的广播地址255.255.255.255
            */
            try {
                inetAddress = InetAddress.getByName("255.255.255.255");
            } catch (UnknownHostException ex) {
                Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
            }
            try {
                client = new DatagramSocket();
            } catch (SocketException ex) {
                Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
            }
            sendPack = new DatagramPacket(message, message.length, inetAddress,8888);
            try {
                client.send(sendPack);
            } catch (IOException ex) {
                Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
            }
            //System.out.println("Client send a message complete");
            client.close();
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void sendTo(InetAddress inetAddress,String text){
        try {
            byte[] message=text.getBytes("gb2312");
            DatagramPacket sendPacket;
            try {
                client = new DatagramSocket();
                sendPacket = new DatagramPacket(message, message.length, inetAddress,8888);
                try {
                    client.send(sendPacket);
                } catch (IOException ex) {
                    Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
                }
                //System.out.println("Test:"+ "单播发送成功");
            } catch (SocketException ex) {
                Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
            }
            client.close();
            
            
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
        }
       
        
    }
    
    public void receive() { 
        System.out.println(String.format("%tF %tT ", Calendar.getInstance(),Calendar.getInstance())+"Server start...");
        String message;
        while (true)
        {
            try {
                try {
                    server.receive(receive);
                } catch (IOException ex) {
                    Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
                }
                byte[] recvByte = Arrays.copyOfRange(receive.getData(), 0,receive.getLength());
                message = new String(recvByte,"gb2312");
                if (message.startsWith(protocolFlag)){
                //输出
                System.out.println(String.format("%tF %tT ", Calendar.getInstance(),Calendar.getInstance())+"receive:" + receive.getAddress()+"/"+message);
                //分析传输过来的数据内容
                this.analyze(receive,message);
                }
            } catch (UnsupportedEncodingException ex) {
                        Logger.getLogger(Broadcast.class.getName()).log(Level.SEVERE, null, ex);
            }   
        }
    }
    public void analyze(DatagramPacket receive,String message){
        String[] split = message.split("#");
        onlineUser=new OnlineUser(split[2],split[3],receive.getAddress());
        switch (split[1]){
            case "online":
                //把该主机加入到用户列表，然后向该主机推送我已经在线的消息
                this.addOnlineUser(onlineUser);
                this.pushOnline();                
                this.flushOnlineUsersListShow(onlineUsers);
                break;
            case "pushOnline":
                //把该主机加入到用户列表
                this.addOnlineUser(onlineUser);
                this.flushOnlineUsersListShow(onlineUsers);
                break;
            case "offline":
                onlineUsers.remove(onlineUser);
                this.flushOnlineUsersListShow(onlineUsers);
                break;
            case "message":
                this.receiveMessage(message);
                break;
            default:
                System.out.println("message type is wrong");
        }
        
    }
    
    //群发上线消息
    public void online() {
        type = "online";
        message=protocolFlag+flag+type+flag+hostname+flag+nickname;
        //System.out.println("Test:"+message);
        this.send(message);
    }
    
    //单发已经在线消息
    public void pushOnline(InetAddress inetAddress){
        type = "pushOnline";
        message=protocolFlag+flag+type+flag+hostname+flag+nickname;
        this.sendTo(inetAddress,message);
    }
    //单发已经在线消息
    public void pushOnline(){
        type = "pushOnline";
        message=protocolFlag+flag+type+flag+hostname+flag+nickname;
        this.send(message);
    }
    //群发离线消息
    public void offline() {
        type = "offline";
        message=protocolFlag+flag+type+flag+hostname+flag+nickname;
        //System.out.println("Test:"+message);
        this.send(message);
    }
    
    public void sendMessage(InetAddress inetAddress,String text) {
        type = "message";
        message=protocolFlag+flag+type+flag+hostname+flag+nickname+flag+showFont(font)+flag+showColor(fontColor)+flag+text.trim();
        //System.out.println("Test:"+message);
        this.sendTo(inetAddress,message);
    }
    public void sendMessages(String text) {
        type = "message";
        message=protocolFlag+flag+type+flag+hostname+flag+nickname+flag+showFont(font)+flag+showColor(fontColor)+flag+text.trim();
        //System.out.println("Test:"+message);
        this.send(message);
    }
    public void receiveMessage(String message){
        this.chatUI.showMessage(message);
    }
    public void flushOnlineUsersListShow(ArrayList onlineUsers){
        this.chatUI.flushOnlineUsersListShow(onlineUsers);
    }
    public String showColor(Color fontColor){
        String showColor;
        showColor = this.fontColor.getRed()+":"+this.fontColor.getGreen()+":"+this.fontColor.getBlue();
        return showColor;
    }
    public String showFont(Font font){
        String showFont;
        showFont=this.font.getFamily()+":"+this.font.getStyle()+":"+this.font.getSize();
        return showFont;
    }
    public void addOnlineUser(OnlineUser onlineUser){
        if (onlineUsers.isEmpty()){
            onlineUsers.add(onlineUser); 
        }else{
            Iterator<OnlineUser> it=onlineUsers.iterator();
            while (it.hasNext()){
                if (it.next().equals(onlineUser)){
                    it.remove();
                    break;
                }
            }
            onlineUsers.add(onlineUser);
        }
        
    }

    @Override
    public void run(){
        this.receive();
    }
}
